home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1995 November / EnigmA AMIGA RUN 02 (1995)(G.R. Edizioni)(IT)[!][issue 1995-11][Skylink CD].iso / earcd / util / misc / frodo.lha / src / 1541.asm next >
Assembly Source File  |  1995-01-24  |  30KB  |  1,546 lines

  1. *
  2. * 1541.asm - 1541-Emulation, Dateihandling
  3. *
  4. * Copyright (C) 1994-1995 by Christian Bauer
  5. *
  6.  
  7. *
  8. * Anmerkungen:
  9. * ------------
  10. *
  11. * Aufrufkonventionen:
  12. *  - Die Routinen IECOut#? und IECIn geben in d0 den Status zurück.
  13. *    Dieser wird von den aufrufenden Routinen mit dem C64-Statusbyte
  14. *    ($90) verodert.
  15. *  - Die Routinen dürfen nur d0-d1/a0-a1 verändern
  16. *
  17. * Funktionsweise:
  18. *  - Am IEC-Bus gibt es drei Sorten von Geräten: Controller, Listener
  19. *    und Talker. Der Controller sind immer wir, zusätzlich können wir
  20. *    wahlweise Talker und Listener sein. Es kann immer nur einen Talker
  21. *    und einen Listener geben (am echten IEC-Bus sind mehrere Listener
  22. *    erlaubt, aber hier nicht).
  23. *  - Die Geräte, die angesprochen werden, sind entweder real am IEC-Kabel
  24. *    oder werden hier emuliert. Für jedes emulierte Laufwerk existiert
  25. *    eine eigene Datenstruktur (Drv?Data). Ein Zeiger darauf wird bei
  26. *    Talk/Listen in TalkerData/ListenerData gespeichert und steht den
  27. *    nachfolgend aufgerufenen Routinen zur Verfügung, damit sich diese
  28. *    um das jeweils angesprochene Laufwerk kümmern.
  29. *  - Bei Geräten am Kabel wird #?Data nicht benutzt, da die Routinen
  30. *    dann die Daten im wesentlichen einfach an den IEC-Bus durchreichen
  31. *
  32. * EOI/EOF:
  33. *  - Im Gegensatz zum Amiga, wo der EOF-Zustand erst nach dem Lesen
  34. *    des letzten Bytes erkannt wird, wird beim IEC-Bus das EOF
  35. *    gleichzeitig mit dem letzten Byte gesendet. Daher verwenden die
  36. *    Leseroutinen einen Puffer, in dem immer ein Byte bereitsteht.
  37. *
  38. * Directory-Emulation:
  39. *  - Wird das Directory geöffnet (Dateiname "$"), wird in T: eine
  40. *    temporäre Datei angelegt, die vom Aufbau genau einem 1541-Directory
  41. *    entspricht und diese Datei geöffnet. Sie kann dann mit den ganz
  42. *    normalen Lesebefehlen verarbeitet werden.
  43. *
  44. * Inkompatibilitäten/Verbesserungen:
  45. *  - Es kann nur ein Listener gleichzeitig aktiv sein
  46. *  - Kein Kommandokanal implementiert
  47. *  - Beim Empfang des Dateinamens sollte er auf Pufferüberlauf prüfen
  48. *
  49.  
  50.         MACHINE    68020
  51.  
  52.         INCLUDE    "exec/types.i"
  53.         INCLUDE    "exec/macros.i"
  54.         INCLUDE    "dos/dos.i"
  55.         INCLUDE    "resources/misc.i"
  56.         INCLUDE    "hardware/cia.i"
  57.  
  58.         XREF    _SysBase
  59.         XREF    _DOSBase
  60.         XREF    _CiaBase
  61.         XREF    _MiscBase
  62.  
  63.         XREF    _ciaaprb
  64.         XREF    _ciaaddrb
  65.  
  66.         XDEF    Open1541
  67.         XDEF    Close1541
  68.         XDEF    ChangedDirs
  69.         XDEF    CloseIEC
  70.         XDEF    ChangedIEC
  71.         XDEF    IECOut
  72.         XDEF    IECOutATN
  73.         XDEF    IECOutSec
  74.         XDEF    IECIn
  75.         XDEF    IECSetATN
  76.         XDEF    IECRelATN
  77.         XDEF    IECTurnaround
  78.         XDEF    IECRelease
  79.         XDEF    IECIsOpen
  80.  
  81.         XDEF    Dir8        ;Prefs
  82.         XDEF    Dir9
  83.         XDEF    Dir10
  84.         XDEF    Dir11
  85.         XDEF    Drv8IsIEC
  86.         XDEF    Drv9IsIEC
  87.         XDEF    Drv10IsIEC
  88.         XDEF    Drv11IsIEC
  89.         XDEF    OtherIEC
  90.  
  91.         SECTION    "CODE",CODE
  92.  
  93.  
  94. **
  95. ** Definitionen
  96. **
  97.  
  98. ; Datenstruktur für ein Laufwerk
  99.  STRUCTURE DRVDATA,0
  100.     BYTE    drv_ErrorCode        ;Letzter Fehlercode (ERR_#?)
  101.     BYTE    drv_ReadBuf        ;Byte-Puffer zum Lesen aus Dateien
  102.     BYTE    drv_IsIEC        ;Laufwerk wird über IEC-Kabel angesprochen
  103.     BYTE    pad0
  104.     STRUCT    drv_Handles,16*4    ;FileHandles für alle 16 Sekundäradressen
  105.     APTR    drv_NamePtr        ;Zeiger in Dateinamen, für Open/IECOut
  106.     APTR    drv_ErrorPtr        ;Zeiger in Fehlermeldung
  107.     APTR    drv_Lock        ;Lock des Verzeichnisses des Laufwerks
  108.  LABEL drv_SIZEOF
  109.  
  110. ; Register (müssen mit den Definitionen in 6510.asm übereinstimmen!)
  111. RAMPTR        EQUR    a4    ;Zeiger auf C64-RAM
  112.  
  113. ; C64-Status-Codes
  114. ST_OK        = 0    ;Alles klar
  115. ST_READ_TIMEOUT    = $02    ;Timeout beim Lesen
  116. ST_TIMEOUT    = $03    ;Timeout
  117. ST_EOF        = $40    ;End of file
  118. ST_NOTPRESENT    = $80    ;Device not present
  119.  
  120. ; IEC-Befehlscodes
  121. CMD_DATA    = $60
  122. CMD_CLOSE    = $e0
  123. CMD_OPEN    = $f0
  124.  
  125. ; Fehlercodes (genauer: Die Nummer des zugeh. Fehlertextes)
  126. ERR_OK        = 0    ;00: OK
  127. ERR_STARTUP    = 1    ;Einschaltmeldung
  128. ERR_FILENOTFOUND = 2    ;62: FILE NOT FOUND
  129.  
  130. ; Makros für IEC-Kabel
  131. DATA_HI        MACRO
  132.         bclr    #5,_ciaaprb
  133.         ENDM
  134.  
  135. DATA_LO        MACRO
  136.         bset    #5,_ciaaprb
  137.         ENDM
  138.  
  139. CLOCK_HI    MACRO
  140.         bclr    #4,_ciaaprb
  141.         ENDM
  142.  
  143. CLOCK_LO    MACRO
  144.         bset    #4,_ciaaprb
  145.         ENDM
  146.  
  147. ATN_HI        MACRO
  148.         bclr    #3,_ciaaprb
  149.         ENDM
  150.  
  151. ATN_LO        MACRO
  152.         bset    #3,_ciaaprb
  153.         ENDM
  154.  
  155. LINE_RELEASE    MACRO
  156.         ATN_HI
  157.         bsr    Wait40us
  158.         CLOCK_HI
  159.         DATA_HI
  160.         ENDM
  161.  
  162. ; Data -> Carry, Clock -> Negative
  163. GET_DATA_CLOCK    MACRO
  164. \@1$        move.b    _ciaaprb,d0
  165.         cmp.b    _ciaaprb,d0
  166.         bne    \@1$
  167.         add.b    d0,d0
  168.         ENDM
  169.  
  170. WAIT_CLOCK_HI    MACRO
  171. \@1$        GET_DATA_CLOCK
  172.         bpl    \@1$
  173.         ENDM
  174.  
  175. WAIT_CLOCK_LO    MACRO
  176. \@1$        GET_DATA_CLOCK
  177.         bmi    \@1$
  178.         ENDM
  179.  
  180. WAIT_DATA_HI    MACRO
  181. \@1$        GET_DATA_CLOCK
  182.         bcc    \@1$
  183.         ENDM
  184.  
  185. WAIT_DATA_LO    MACRO
  186. \@1$        GET_DATA_CLOCK
  187.         bcs    \@1$
  188.         ENDM
  189.  
  190.  
  191. **
  192. ** 1541-Emulation starten
  193. **
  194.  
  195. ; Einschaltmeldung bereitstellen
  196. Open1541    move.b    #ERR_STARTUP,Drv8Data+drv_ErrorCode
  197.         move.b    #ERR_STARTUP,Drv9Data+drv_ErrorCode
  198.         move.b    #ERR_STARTUP,Drv10Data+drv_ErrorCode
  199.         move.b    #ERR_STARTUP,Drv11Data+drv_ErrorCode
  200.  
  201. ; Locks der Verzeichnisse holen
  202.         move.l    _DOSBase,a6
  203.         bra    OpenLocks
  204.  
  205.  
  206. **
  207. ** 1541-Emulation beenden
  208. **
  209.  
  210. ; Alle Dateien schließen
  211. Close1541    move.l    _DOSBase,a6
  212.  
  213.         lea    Drv8Data+drv_Handles,a0
  214.         bsr    FreeHandles
  215.         lea    Drv9Data+drv_Handles,a0
  216.         bsr    FreeHandles
  217.         lea    Drv10Data+drv_Handles,a0
  218.         bsr    FreeHandles
  219.         lea    Drv11Data+drv_Handles,a0
  220.         bsr    FreeHandles
  221.  
  222. ; Alle Locks freigeben
  223.         bsr    FreeLocks
  224.  
  225. ; Temporäre Datei löschen
  226.         move.l    #TempFileName,d1
  227.         JMPLIB    DeleteFile
  228.  
  229. FreeHandles    moveq    #15,d7        ;16 Kanäle
  230. 2$        move.l    (a0)+,d1
  231.         beq    1$
  232.         clr.l    -4(a0)        ;FileHandle löschen
  233.         JSRLIB    Close
  234. 1$        dbra    d7,2$
  235.         rts
  236.  
  237.  
  238. **
  239. ** Die Verzeichnisse haben sich geändert: Neue Locks holen
  240. **
  241.  
  242. ChangedDirs    move.l    _DOSBase,a6
  243.         bsr    FreeLocks
  244.         bra    OpenLocks
  245.  
  246.  
  247. **
  248. ** IEC-Einstellungen wurden verändert
  249. ** Rückgabe: d0=0 Alles OK
  250. **           d0=1 Parallelport belegt
  251. **           d0=2 Kein Timer frei
  252. **
  253.  
  254. ; Einstellungen übertragen
  255. ChangedIEC    moveq    #0,d1
  256.         move.w    Drv8IsIEC,d0
  257.         or.b    d0,d1
  258.         move.b    d0,Drv8Data+drv_IsIEC
  259.         move.w    Drv9IsIEC,d0
  260.         or.b    d0,d1
  261.         move.b    d0,Drv9Data+drv_IsIEC
  262.         move.w    Drv10IsIEC,d0
  263.         or.b    d0,d1
  264.         move.b    d0,Drv10Data+drv_IsIEC
  265.         move.w    Drv11IsIEC,d0
  266.         or.b    d0,d1
  267.         move.b    d0,Drv11Data+drv_IsIEC
  268.         or.w    OtherIEC,d1
  269.  
  270. ; IEC öffnen, wenn mindestens ein Gerät mit IEC laufen soll,
  271. ; sonst schließen
  272.         tst.b    d1
  273.         beq    CloseIEC
  274.         bra    OpenIEC
  275.  
  276.  
  277. **
  278. ** Auf Benutzung des IEC-Kabels vorbereiten
  279. ** Rückgabe: d0=0 Alles OK
  280. **           d0=1 Parallelport belegt
  281. **           d0=2 Kein Timer frei
  282. **
  283.  
  284. OpenIEC        move.l    a6,-(sp)
  285.         tst.b    IECIsOpen    ;Kann auch mehrmals aufgerufen werden
  286.         bne    OIECOK
  287.  
  288. ; Parallelport belegen
  289.         move.l    _MiscBase,a6
  290.         moveq    #MR_PARALLELPORT,d0
  291.         lea    ParPortName,a1
  292.         JSRLIB    AllocMiscResource
  293.         tst.l    d0
  294.         bne    OIECNoPort
  295.  
  296.         move.b    #$00,_ciaaprb    ;Port inaktiv
  297.         move.b    #$38,_ciaaddrb    ;DDR konfigurieren
  298.  
  299. ; Timer A belegen
  300.         move.l    _CiaBase,a6
  301.         lea    TimerInterrupt,a1
  302.         moveq    #CIAICRB_TA,d0
  303.         JSRLIB    AddICRVector
  304.         tst.l    d0
  305.         bne    1$
  306.  
  307. ; Gelungen
  308.         move.b    #CIAICRB_TA,WhichTimer
  309.         move.b    #CIAICRF_TA,WhichTimerMask
  310.         move.l    #$bfe401,CiaTimerReg
  311.         move.l    #$bfee01,CiaControlReg
  312.         bra    3$
  313.  
  314. ; Nicht gelungen, dann Timer B probieren
  315. 1$        lea    TimerInterrupt,a1
  316.         moveq    #CIAICRB_TB,d0
  317.         JSRLIB    AddICRVector
  318.         tst.l    d0
  319.         bne    2$
  320.  
  321. ; Gelungen
  322.         move.b    #CIAICRB_TB,WhichTimer
  323.         move.b    #CIAICRF_TB,WhichTimerMask
  324.         move.l    #$bfe601,CiaTimerReg
  325.         move.l    #$bfef01,CiaControlReg
  326.         bra    3$
  327.  
  328. ; Nicht gelungen, dann Parallelport wieder freigeben
  329. 2$        move.b    #$00,_ciaaddrb    ;Port auf Eingabe
  330.  
  331.         move.l    _MiscBase,a6
  332.         moveq    #MR_PARALLELPORT,d0
  333.         JSRLIB    FreeMiscResource
  334.  
  335.         moveq    #2,d0        ;Kein Timer frei
  336.         move.l    (sp)+,a6
  337.         rts
  338.  
  339. ; Alles klar, Timer-Interrupt abschalten und Timer stoppen
  340. 3$        move.b    WhichTimerMask,d0
  341.         JSRLIB    AbleICR
  342.  
  343.         move.l    CiaControlReg,a0
  344.         and.b    #$80,(a0)
  345.  
  346.         st.b    IECIsOpen
  347. OIECOK        moveq    #0,d0        ;Alles OK
  348.         move.l    (sp)+,a6
  349.         rts
  350.  
  351. OIECNoPort    moveq    #1,d0        ;Parallelport belegt
  352.         move.l    (sp)+,a6
  353.         rts
  354.  
  355.  
  356. **
  357. ** Benutzung des IEC-Kabels beenden
  358. ** Rückgabe: d0=0
  359. **
  360.  
  361. CloseIEC    tst.b    IECIsOpen
  362.         beq    1$
  363.  
  364.         move.b    #$00,_ciaaddrb    ;Port auf Eingabe
  365.  
  366.         move.l    a6,-(sp)    ;Parallelport freigeben
  367.         move.l    _MiscBase,a6
  368.         moveq    #MR_PARALLELPORT,d0
  369.         JSRLIB    FreeMiscResource
  370.  
  371.         move.l    CiaControlReg,a0 ;Timer stoppen
  372.         and.b    #$80,(a0)
  373.  
  374.         move.l    _CiaBase,a6
  375.         lea    TimerInterrupt,a1
  376.         move.b    WhichTimer,d0
  377.         JSRLIB    RemICRVector
  378.  
  379.         move.l    (sp)+,a6
  380.         clr.b    IECIsOpen
  381.  
  382. 1$        moveq    #0,d0
  383.         rts
  384.  
  385.  
  386. *
  387. * Locks freigeben
  388. *
  389.  
  390. FreeLocks    move.l    Drv8Data+drv_Lock,d1
  391.         beq    1$
  392.         JSRLIB    UnLock
  393. 1$        move.l    Drv9Data+drv_Lock,d1
  394.         beq    2$
  395.         JSRLIB    UnLock
  396. 2$        move.l    Drv10Data+drv_Lock,d1
  397.         beq    3$
  398.         JSRLIB    UnLock
  399. 3$        move.l    Drv11Data+drv_Lock,d1
  400.         beq    4$
  401.         JSRLIB    UnLock
  402. 4$        rts
  403.  
  404. *
  405. * Locks holen
  406. *
  407.  
  408. OpenLocks    move.l    #Dir8,d1
  409.         move.l    #ACCESS_READ,d2
  410.         JSRLIB    Lock
  411.         move.l    d0,Drv8Data+drv_Lock
  412.  
  413.         move.l    #Dir9,d1
  414.         move.l    #ACCESS_READ,d2
  415.         JSRLIB    Lock
  416.         move.l    d0,Drv9Data+drv_Lock
  417.  
  418.         move.l    #Dir10,d1
  419.         move.l    #ACCESS_READ,d2
  420.         JSRLIB    Lock
  421.         move.l    d0,Drv10Data+drv_Lock
  422.  
  423.         move.l    #Dir11,d1
  424.         move.l    #ACCESS_READ,d2
  425.         JSRLIB    Lock
  426.         move.l    d0,Drv11Data+drv_Lock
  427.         rts
  428.  
  429.  
  430. **
  431. ** IECOut - Ein Byte ausgeben
  432. ** d0.b: Byte
  433. ** d1.b: <0: EOI-Flag
  434. **
  435.  
  436. IECOut        tst.b    ListenerIsIEC    ;Listener am IEC-Kabel?
  437.         bne    IECByteOut    ;Ja, dann Byte über Kabel senden
  438.         tst.b    ListenerActive    ;Wurde ein Gerät angesprochen?
  439.         beq    1$
  440.  
  441.         cmp.b    #CMD_OPEN,ReceivedCmd
  442.         beq    OpenOut
  443.         cmp.b    #CMD_DATA,ReceivedCmd
  444.         beq    DataOut
  445.  
  446. 1$        move.b    #ST_TIMEOUT,d0    ;Kein Listener aktiv oder kein gültiger Befehl
  447.         rts
  448.  
  449.  
  450. **
  451. ** IECOutATN - Ein Byte mit ATN ausgeben (Talk/Listen/Untalk/Unlisten)
  452. ** d0.b: Byte
  453. **
  454.  
  455. IECOutATN    clr.b    SecAddr        ;Befehl kommt mit der Sekundäradresse danach
  456.         clr.b    ReceivedCmd
  457.  
  458.         move.b    d0,d1
  459.         and.b    #$0f,d0        ;d0.b: Gerätenummer
  460.         and.b    #$f0,d1        ;d1.b: Funktion
  461.  
  462.         st.b    Listening    ;Funktion auswerten
  463.         cmp.b    #$20,d1        ;Bei Listen ist das Flag Listening gesetzt
  464.         beq    Listen
  465.         clr.b    Listening
  466.         cmp.b    #$30,d1
  467.         beq    Unlisten
  468.         cmp.b    #$40,d1
  469.         beq    Talk
  470.         cmp.b    #$50,d1
  471.         beq    Untalk
  472.  
  473.         move.b    #ST_TIMEOUT,d0    ;Ungültige Funktion
  474.         rts
  475.  
  476.  
  477. **
  478. ** IECOutSec - Sekundäradresse ausgeben
  479. ** d0.b: Sekundäradresse
  480. **
  481.  
  482. IECOutSec    tst.b    Listening    ;Nach Listen oder nach Talk?
  483.         beq    1$
  484.  
  485.         tst.b    ListenerIsIEC    ;Nach Listen: Listener am IEC-Kabel?
  486.         bne    IECByteOutSec
  487.         tst.b    ListenerActive    ;Wurde ein Gerät angesprochen?
  488.         beq    2$
  489.  
  490.         move.b    d0,d1
  491.         and.b    #$0f,d0        ;Sekundäradresse
  492.         move.b    d0,SecAddr
  493.         and.b    #$f0,d1        ;und Befehlscode speichern
  494.         move.b    d1,ReceivedCmd
  495.         bra    SecListen    ;Sek.adr nach Listen
  496.  
  497. 1$        tst.b    TalkerIsIEC    ;Nach Talk: Talker am IEC-Kabel?
  498.         bne    IECByteOutSec
  499.         tst.b    TalkerActive    ;Wurde ein Gerät angesprochen?
  500.         beq    2$
  501.  
  502.         move.b    d0,d1
  503.         and.b    #$0f,d0        ;Sekundäradresse
  504.         move.b    d0,SecAddr
  505.         and.b    #$f0,d1        ;und Befehlscode speichern
  506.         move.b    d1,ReceivedCmd
  507.         bra    SecTalk        ;Sek.adr nach Talk
  508.  
  509. 2$        move.b    #ST_TIMEOUT,d0    ;Es erfolgte kein Listen/Talk
  510.         rts
  511.  
  512.  
  513. **
  514. ** IECIn - Ein Byte einlesen
  515. ** RÜckgabe: d1.b: Byte
  516. **
  517.  
  518. IECIn        tst.b    TalkerIsIEC    ;Talker am IEC-Kabel?
  519.         bne    IECByteIn
  520.         tst.b    TalkerActive    ;Wurde ein Gerät angesprochen?
  521.         beq    1$
  522.  
  523.         cmp.b    #CMD_DATA,ReceivedCmd
  524.         beq    DataIn
  525.  
  526. 1$        move.b    #ST_TIMEOUT,d0    ;Kein Talk bzw. kein CMD_DATA
  527.         clr.b    d1
  528.         rts
  529.  
  530.  
  531. **
  532. ** IECSetATN - ATN setzen (für Untalk)
  533. **
  534.  
  535. IECSetATN    tst.b    TalkerIsIEC    ;Nur bei IEC-Geräten etwas machen
  536.         beq    1$
  537.         CLOCK_LO
  538.         ATN_LO
  539. 1$        rts
  540.  
  541.  
  542. **
  543. ** IECRelATN - ATN wegnehmen
  544. **
  545.  
  546. IECRelATN    tst.b    IECIsOpen
  547.         beq    1$
  548.         ATN_HI
  549.         bsr    Wait20us
  550. 1$        rts
  551.  
  552.  
  553. **
  554. ** IECTurnaround - Talk-attention turn around
  555. **
  556.  
  557. IECTurnaround    tst.b    TalkerIsIEC    ;Nur bei IEC-Geräten etwas machen
  558.         beq    1$
  559.         move.l    a6,-(sp)
  560.         move.l    _SysBase,a6
  561.         JSRLIB    Disable
  562.         DATA_LO
  563.         bsr    Wait20us
  564.         ATN_HI
  565.         CLOCK_HI
  566.         WAIT_CLOCK_LO
  567.         bsr    Wait60us
  568.         JSRLIB    Enable
  569.         move.l    (sp)+,a6
  570. 1$        rts
  571.  
  572.  
  573. **
  574. ** IECRelease - System line release
  575. **
  576.  
  577. IECRelease    tst.b    IECIsOpen
  578.         beq    1$
  579.         LINE_RELEASE
  580. 1$        rts
  581.  
  582.  
  583. *
  584. * Listen
  585. * d0.b: Gerätenummer
  586. * d1.b: Funktion
  587. *
  588.  
  589. Listen        cmp.b    #8,d0        ;Gerät zwischen 8 und 11?
  590.         blo    ListenOther
  591.         cmp.b    #11,d0
  592.         bhi    ListenOther
  593.  
  594.         moveq    #0,d1        ;Ja, Zeiger auf Datenbereich holen
  595.         move.b    d0,d1
  596.         subq.b    #8,d1
  597.         move.l    (DrvTab,d1.w*4),a0
  598.         tst.b    drv_IsIEC(a0)    ;IEC-Gerät?
  599.         bne    ListenIEC
  600.         tst.l    drv_Lock(a0)    ;Nein, Verzeichnis vorhanden?
  601.         beq    ListenNotPr
  602.  
  603.         move.l    a0,ListenerData    ;Ja, Zeiger auf Datenbereich sichern
  604.         st.b    ListenerActive    ;Listener ist aktiv
  605.         clr.b    ListenerIsIEC
  606.         moveq    #ST_OK,d0
  607.         rts
  608.  
  609. ; Anderes Gerät außer 8..11
  610. ListenOther    tst.w    OtherIEC
  611.         beq    ListenNotPr
  612.  
  613. ; Listen über IEC-Kabel
  614. ListenIEC    move.l    a0,ListenerData    ;Zeiger auf Datenbereich sichern
  615.  
  616.         moveq    #$20,d1        ;Listen über Kabel senden
  617.         bsr    IECByteOutATN
  618.         cmp.b    #ST_NOTPRESENT,d0
  619.         beq    ListenNotPr
  620.         st.b    ListenerIsIEC    ;Gelungen, Listener ist aktiv
  621.         rts
  622.  
  623. ; Gerät nicht vorhanden
  624. ListenNotPr    move.b    #ST_NOTPRESENT,d0
  625.         clr.b    ListenerActive
  626.         clr.b    ListenerIsIEC
  627.         rts
  628.  
  629.  
  630. *
  631. * Talk
  632. * d0.b: Gerätenummer
  633. * d1.b: Funktion
  634. *
  635.  
  636. Talk        cmp.b    #8,d0        ;Gerät zwischen 8 und 11?
  637.         blo    TalkOther
  638.         cmp.b    #11,d0
  639.         bhi    TalkOther
  640.  
  641.         moveq    #0,d1        ;Ja, Zeiger auf Datenbereich holen
  642.         move.b    d0,d1
  643.         subq.b    #8,d1
  644.         move.l    (DrvTab,d1.w*4),a0
  645.         tst.b    drv_IsIEC(a0)    ;IEC-Gerät?
  646.         bne    TalkIEC
  647.         tst.l    drv_Lock(a0)    ;Nein, Verzeichnis vorhanden?
  648.         beq    TalkNotPr
  649.  
  650.         move.l    a0,TalkerData    ;Ja, Zeiger auf Datenbereich sichern
  651.         st.b    TalkerActive    ;Talker ist aktiv
  652.         clr.b    TalkerIsIEC
  653.         moveq    #ST_OK,d0
  654.         rts
  655.  
  656. ; Anderes Gerät außer 8..11
  657. TalkOther    tst.w    OtherIEC
  658.         beq    TalkNotPr
  659.  
  660. ; Talk über IEC-Kabel
  661. TalkIEC        move.l    a0,TalkerData    ;Zeiger auf Datenbereich sichern
  662.  
  663.         moveq    #$40,d1        ;Talk über Kabel senden
  664.         bsr    IECByteOutATN
  665.         cmp.b    #ST_NOTPRESENT,d0
  666.         beq    TalkNotPr
  667.         st.b    TalkerIsIEC    ;Gelungen, Talker ist aktiv
  668.         rts
  669.  
  670. ; Gerät nicht vorhanden
  671. TalkNotPr    move.b    #ST_NOTPRESENT,d0
  672.         clr.b    TalkerActive
  673.         clr.b    TalkerIsIEC
  674.         rts
  675.  
  676.  
  677. *
  678. * Unlisten
  679. * d0.b: Gerätenummer
  680. * d1.b: Funktion
  681. *
  682.  
  683. Unlisten    tst.b    ListenerIsIEC    ;Listener am IEC-Kabel?
  684.         beq    1$
  685.         bsr    IECByteOutATN    ;Ja, Unlisten über Kabel senden
  686.         bra    2$
  687.  
  688. 1$        moveq    #ST_OK,d0
  689. 2$        clr.b    ListenerActive    ;Gerät nicht mehr aktiv
  690.         clr.b    ListenerIsIEC
  691.         rts
  692.  
  693. *
  694. * Untalk
  695. * d0.b: Gerätenummer
  696. * d1.b: Funktion
  697. *
  698.  
  699. Untalk        tst.b    TalkerIsIEC    ;Talker am IEC-Kabel?
  700.         beq    1$
  701.         bsr    IECByteOutATN    ;Ja, Untalk über Kabel senden
  702.         bra    2$
  703.  
  704. 1$        moveq    #ST_OK,d0
  705. 2$        clr.b    TalkerActive    ;Gerät nicht mehr aktiv
  706.         clr.b    TalkerIsIEC
  707.         rts
  708.  
  709.  
  710. *
  711. * SecListen - Sekundäradresse nach Listen
  712. * d0.b: Sekundäradresse
  713. * d1.b: Befehlscode
  714. *
  715.  
  716. SecListen    cmp.b    #CMD_OPEN,d1
  717.         beq    SecListenOpen
  718.         cmp.b    #CMD_CLOSE,d1
  719.         beq    SecListenClose
  720.  
  721.         moveq    #ST_OK,d0
  722.         rts
  723.  
  724.  
  725. *
  726. * Open-Befehl: Auf Empfang des Dateinamens vorbereiten
  727. *
  728.  
  729. SecListenOpen    move.l    ListenerData,a0
  730.         move.l    #NameBuf,drv_NamePtr(a0)
  731.         moveq    #ST_OK,d0
  732.         rts
  733.  
  734.  
  735. *
  736. * Close-Befehl: Datei schließen
  737. *
  738.  
  739. SecListenClose    movem.l    a2/a4/a6,-(sp)
  740.         move.l    _DOSBase,a6
  741.         move.l    ListenerData,a4
  742.  
  743.         moveq    #0,d0        ;Zeiger auf FileHandle holen
  744.         move.b    SecAddr,d0
  745.         lea    drv_Handles(a4,d0.w*4),a2
  746.         move.l    (a2),d1        ;Datei schließen, wenn geöffnet
  747.         beq    1$
  748.         JSRLIB    Close
  749.         clr.l    (a2)
  750.  
  751. 1$        movem.l    (sp)+,a2/a4/a6
  752.         moveq    #ST_OK,d0
  753.         rts
  754.  
  755.  
  756. *
  757. * SecTalk - Sekundäradresse nach Talk
  758. * d0.b: Sekundäradresse
  759. * d1.b: Befehlscode
  760. *
  761.  
  762. SecTalk        cmp.b    #15,d0        ;Kanal 15 (Fehlerkanal)?
  763.         beq    SecTalk15
  764.  
  765.         moveq    #ST_OK,d0
  766.         rts
  767.  
  768.  
  769. *
  770. * Kanal 15: Fehlermeldung bereitstellen
  771. *
  772.  
  773. SecTalk15    move.l    TalkerData,a1
  774.         lea    ErrorTab,a0    ;Zeiger auf Fehlermeldung laden
  775.         moveq    #0,d0
  776.         move.b    drv_ErrorCode(a1),d0
  777.         move.l    (a0,d0.w*4),drv_ErrorPtr(a1)
  778.         move.b    #ERR_OK,drv_ErrorCode(a1) ;Fehlercode löschen
  779.         moveq    #ST_OK,d0
  780.         rts
  781.  
  782.  
  783. *
  784. * Byte nach Open-Befehl: Zeichen im Dateinamen speichern, bei EOI Datei öffnen
  785. * d0.b: Byte
  786. * d1.b: EOI-Flag
  787. *
  788.  
  789. OpenOut        cmp.b    #15,SecAddr    ;Kanal 15 (Kommandokanal)?
  790.         beq    1$
  791.  
  792.         move.l    ListenerData,a0    ;Nein, Zeichen speichern
  793.         move.l    drv_NamePtr(a0),a1
  794.         bsr    ConvTo64    ;Zeichensatz wandeln
  795.         move.b    d0,(a1)+
  796.         move.l    a1,drv_NamePtr(a0)
  797.  
  798.         tst.b    d1        ;EOI: Datei öffnen
  799.         bmi    OpenFile
  800.  
  801. 1$        moveq    #ST_OK,d0
  802.         rts
  803.  
  804.  
  805. *
  806. * Dateiname nach Open-Befehl empfangen: Datei öffnen
  807. *
  808.  
  809. OpenFile    movem.l    d2-d4/a2/a4/a6,-(sp)
  810.         move.l    _DOSBase,a6
  811.         move.l    ListenerData,a4
  812.  
  813. ; Zeiger auf FileHandle nach a2 holen
  814.         moveq    #0,d0
  815.         move.b    SecAddr,d0
  816.         lea    drv_Handles(a4,d0.w*4),a2
  817.  
  818. ; Vorige Datei schließen, wenn noch offen
  819.         move.l    (a2),d1
  820.         beq    1$
  821.         JSRLIB    Close
  822.         clr.l    (a2)
  823. 1$
  824.  
  825. ; Erstes Zeichen des Dateinamens='$'? Dann Directory öffnen
  826.         cmp.b    #'$',NameBuf
  827.         beq    OpenDir
  828.  
  829. ; In das Verzeichnis des Laufwerks wechseln
  830.         move.l    drv_Lock(a4),d1
  831.         JSRLIB    CurrentDir
  832.         move.l    d0,d3
  833.  
  834. ; Dateinamen mit Nullbyte abschließen
  835.         move.l    drv_NamePtr(a4),a0
  836.         clr.b    (a0)
  837.  
  838. ; Modus ermitteln (Sek.adr 0: Laden, Sek.adr 1: Speichern, sonst R/W)
  839.         cmp.b    #0,SecAddr    ;Load?
  840.         bne    2$
  841.         move.l    #MODE_OLDFILE,d2
  842.         bra    4$
  843. 2$        cmp.b    #1,SecAddr    ;Save?
  844.         bne    3$
  845.         move.l    #MODE_NEWFILE,d2
  846.         bra    4$
  847. 3$        move.l    #MODE_READWRITE,d2
  848. 4$
  849.  
  850. ; Datei öffnen und erstes Zeichen lesen
  851.         move.b    #ERR_FILENOTFOUND,drv_ErrorCode(a4) ;Vorgabe: Datei nicht gefunden
  852.         move.l    #NameBuf,d1
  853.         JSRLIB    Open
  854.         move.l    d0,(a2)
  855.         beq    5$
  856.  
  857.         move.b    #ERR_OK,drv_ErrorCode(a4) ;Datei doch gefunden
  858.  
  859.         move.l    d0,d1
  860.         JSRLIB    FGetC
  861.         move.b    d0,drv_ReadBuf(a4)
  862. 5$
  863.  
  864. ; In das ursprüngliche Verzeichnis wechseln
  865.         move.l    d3,d1
  866.         JSRLIB    CurrentDir
  867.  
  868.         movem.l    (sp)+,d2-d4/a2/a4/a6
  869.         moveq    #ST_OK,d0
  870.         rts
  871.  
  872.  
  873. *
  874. * Directory wird geöffnet, temporäre Datei erstellen
  875. *
  876.  
  877. ; Verzeichnis examinieren
  878. OpenDir        move.l    drv_Lock(a4),d1
  879.         move.l    #TheFIB,d2
  880.         JSRLIB    Examine
  881.         tst.l    d0
  882.         beq    ODError
  883.  
  884. ; Gelungen, temp. Datei öffnen
  885.         move.l    #TempFileName,d1
  886.         move.l    #MODE_NEWFILE,d2
  887.         JSRLIB    Open
  888.         move.l    d0,d4        ;d4: FileHandle der temp. Datei
  889.         beq    ODError
  890.  
  891. ; Directory-Titel erzeugen und schreiben
  892.         lea    NameBuf,a0
  893.         move.l    #$01040101,(a0)+ ;Ladeadresse und Verkettung
  894.         clr.w    (a0)+        ;Laufwerksnummer (0) als Zeilennummer
  895.         move.w    #$1222,(a0)+    ;RVS ON und '"'
  896.  
  897.         lea    TheFIB+fib_FileName,a1
  898.         moveq    #15,d1        ;Max. 16 Zeichen Verzeichnisname wandeln
  899. 1$        move.b    (a1)+,d0
  900.         bsr    ConvTo64
  901.         move.b    d0,(a0)+
  902.         dbeq    d1,1$
  903.         bne    2$
  904.         subq.w    #1,a0        ;Den Rest mit Leerzeichen auffüllen
  905. 3$        move.b    #' ',(a0)+
  906.         dbra    d1,3$
  907.         
  908. 2$        move.w    #$2220,(a0)+    ;'" '
  909.         move.l    #'00 2',(a0)+    ;ID und Formatkennzeichen
  910.         move.w    #$4100,(a0)+    ;Abschließendes Nullbyte
  911.  
  912.         move.l    d4,d1        ;Zeile schreiben
  913.         move.l    #NameBuf,d2
  914.         moveq    #32,d3
  915.         JSRLIB    Write
  916.  
  917. ; Schleife für alle Verzeichniseinträge
  918. ; Nächsten Eintrag holen
  919. ODLoop        move.l    drv_Lock(a4),d1
  920.         move.l    #TheFIB,d2
  921.         JSRLIB    ExNext
  922.         tst.l    d0
  923.         beq    ODLoopEnd
  924.  
  925. ; Directory-Zeile erzeugen und schreiben
  926.         lea    NameBuf,a0    ;Zeile mit Leerzeichen löschen
  927.         moveq    #30,d1
  928. 20$        move.b    #' ',(a0)+
  929.         dbra    d1,20$
  930.         clr.b    (a0)        ;und mit Nullbyte abschließen
  931.  
  932.         lea    NameBuf,a0
  933.         move.w    #$0101,(a0)+    ;Verkettung
  934.         move.l    TheFIB+fib_Size,d0 ;Größe in Blocks berechnen
  935.         add.l    #254,d0
  936.         divu.w    #254,d0
  937.         rol.w    #8,d0        ;MSB und LSB vertauschen
  938.         move.w    d0,(a0)+    ;Als Zeilennummer eintragen
  939.         rol.w    #8,d0        ;Bytefolge korrigieren
  940.         addq.l    #1,a0        ;Ein Leerzeichen mindestens
  941.         cmp.w    #10,d0        ;Kleiner als 10?
  942.         bhs    10$
  943.         addq.l    #1,a0        ;Ja, ein Leerzeichen dazunehmen
  944. 10$        cmp.w    #100,d0        ;Kleiner als 100?
  945.         bhs    11$
  946.         addq.l    #1,a0        ;Ja, noch ein Leerzeichen dazunehmen
  947. 11$        move.b    #'"',(a0)+
  948.  
  949.         move.l    a0,-(sp)
  950.         lea    TheFIB+fib_FileName,a1
  951.         moveq    #15,d1        ;Max. 16 Zeichen Dateiname wandeln
  952. 1$        move.b    (a1)+,d0
  953.         bsr    ConvTo64
  954.         move.b    d0,(a0)+
  955.         dbeq    d1,1$
  956.         bne    2$
  957.         subq.w    #1,a0        ;Nullbyte überschreiben
  958. 2$        move.b    #'"',(a0)+    ;Mit '"' abschließen
  959.         move.l    (sp)+,a0
  960.         lea    18(a0),a0    ;An festgelegter Spalte weitermachen
  961.  
  962.         tst.l    TheFIB+fib_DirEntryType ;Typ ermitteln und eintragen
  963.         bmi    ODIsFile
  964.         move.l    #'DIR ',(a0)+
  965.         bra    ODLineEnd
  966. ODIsFile    btst    #FIBB_EXECUTE,TheFIB+fib_Protection+3
  967.         beq    ODIsPRG
  968.         move.l    #'SEQ ',(a0)+
  969.         bra    ODLineEnd
  970. ODIsPRG        move.l    #'PRG ',(a0)+
  971.  
  972. ODLineEnd    move.l    d4,d1        ;Zeile schreiben
  973.         move.l    #NameBuf,d2
  974.         moveq    #32,d3
  975.         JSRLIB    Write
  976.         bra    ODLoop
  977.  
  978. ; Abschlußzeile mit "BLOCKS FREE." erzeugen und schreiben
  979. ODLoopEnd    lea    NameBuf,a0    ;Zeile mit Leerzeichen löschen
  980.         moveq    #28,d1
  981. 20$        move.b    #' ',(a0)+
  982.         dbra    d1,20$
  983.         clr.w    (a0)+        ;Und mit drei Nullbytes abschließen
  984.         clr.b    (a0)
  985.  
  986.         lea    NameBuf,a0
  987.         move.w    #$0101,(a0)+    ;Verkettung
  988.         clr.w    (a0)+        ;Anzahl freier Blöcke (0)
  989.         move.l    #'BLOC',(a0)+
  990.         move.l    #'KS F',(a0)+
  991.         move.l    #'REE.',(a0)+
  992.  
  993.         move.l    d4,d1        ;Zeile schreiben
  994.         move.l    #NameBuf,d2
  995.         moveq    #32,d3
  996.         JSRLIB    Write
  997.  
  998. ; Temp. Datei schließen
  999.         move.l    d4,d1
  1000.         JSRLIB    Close
  1001.  
  1002. ; Und wieder zum Lesen öffnen und das erste Zeichen lesen
  1003.         move.l    #TempFileName,d1
  1004.         move.l    #MODE_OLDFILE,d2
  1005.         JSRLIB    Open
  1006.         move.l    d0,(a2)
  1007.         beq    ODError
  1008.  
  1009.         move.l    d0,d1
  1010.         JSRLIB    FGetC
  1011.         move.b    d0,drv_ReadBuf(a4)
  1012.  
  1013. ODError        movem.l    (sp)+,d2-d4/a2/a4/a6
  1014.         moveq    #ST_OK,d0
  1015.         rts
  1016.  
  1017.  
  1018. *
  1019. * Byte nach Data-Befehl: Zeichen in Datei schreiben
  1020. * d0.b: Byte
  1021. * d1.b: EOI-Flag
  1022. *
  1023.  
  1024. DataOut        cmp.b    #15,SecAddr    ;Kanal 15 (Kommandokanal)?
  1025.         beq    2$
  1026.  
  1027.         movem.l    d2/a2/a4/a6,-(sp)
  1028.         move.l    _DOSBase,a6
  1029.         move.l    ListenerData,a4
  1030.         moveq    #0,d2
  1031.         move.b    d0,d2        ;d2: Byte
  1032.  
  1033.         moveq    #0,d0        ;Zeiger auf FileHandle holen
  1034.         move.b    SecAddr,d0
  1035.         lea    drv_Handles(a4,d0.w*4),a2
  1036.         move.l    (a2),d1        ;Datei geöffnet?
  1037.         beq    1$
  1038.  
  1039.         JSRLIB    FPutC        ;Zeichen schreiben
  1040.         tst.l    d0
  1041.         bmi    1$
  1042.  
  1043.         moveq    #ST_OK,d0
  1044.         movem.l    (sp)+,d2/a2/a4/a6
  1045.         rts
  1046.  
  1047. 1$        move.b    #ST_TIMEOUT,d0    ;Fehler aufgetreten
  1048.         movem.l    (sp)+,d2/a2/a4/a6
  1049.         rts
  1050.  
  1051. 2$        moveq    #ST_OK,d0
  1052.         rts
  1053.  
  1054.  
  1055. *
  1056. * Zeichen aus Datenkanal lesen
  1057. * RÜckgabe: d1.b: Byte
  1058. *
  1059.  
  1060. DataIn        cmp.b    #15,SecAddr    ;Kanal 15 (Fehlerkanal)?
  1061.         beq    Channel15In
  1062.  
  1063.         movem.l    d2/a2/a4/a6,-(sp)
  1064.         move.l    _DOSBase,a6
  1065.         move.l    TalkerData,a4
  1066.  
  1067.         moveq    #0,d0        ;Zeiger auf FileHandle holen
  1068.         move.b    SecAddr,d0
  1069.         lea    drv_Handles(a4,d0.w*4),a2
  1070.         move.l    (a2),d1        ;Datei geöffnet?
  1071.         beq    1$
  1072.  
  1073.         move.b    drv_ReadBuf(a4),d2 ;Zeichen aus dem Puffer holen
  1074.  
  1075.         JSRLIB    FGetC        ;Nächstes Zeichen lesen
  1076.         move.b    d0,drv_ReadBuf(a4) ;und Puffern
  1077.         tst.l    d0
  1078.         bmi    2$        ;EOF? Dann Status setzen
  1079.  
  1080.         moveq    #ST_OK,d0
  1081.         bra    3$
  1082. 2$        move.b    #ST_EOF,d0
  1083. 3$        move.b    d2,d1        ;Zeichen wieder holen
  1084.         movem.l    (sp)+,d2/a2/a4/a6
  1085.         rts
  1086.  
  1087. 1$        move.b    #ST_READ_TIMEOUT,d0    ;Fehler aufgetreten
  1088.         clr.b    d1
  1089.         movem.l    (sp)+,d2/a2/a4/a6
  1090.         rts
  1091.  
  1092.  
  1093. *
  1094. * Aus Kanal 15 lesen
  1095. *
  1096.  
  1097. Channel15In    move.l    TalkerData,a0
  1098.         move.l    drv_ErrorPtr(a0),a1 ;Nächstes Zeichen holen
  1099.         move.b    (a1)+,d1
  1100.         cmp.b    #13,d1        ;CR (letztes Zeichen)?
  1101.         beq    1$
  1102.         move.l    a1,drv_ErrorPtr(a0) ;Nein, Zeiger merken
  1103.         moveq    #ST_OK,d0
  1104.         rts
  1105.  
  1106. 1$        move.b    #ST_EOF,d0    ;Letztes Zeichen: EOF
  1107.         move.l    #OKText,drv_ErrorPtr(a0) ;Falls jemand noch mehr will...
  1108.         rts
  1109.  
  1110.  
  1111. *
  1112. * Umwandlung ASCII->PETSCII
  1113. * Zeichen in d0
  1114. *
  1115.  
  1116. ConvTo64    cmp.b    #'A',d0
  1117.         blo    1$
  1118.         cmp.b    #'Z',d0
  1119.         bhi    2$
  1120.         or.b    #$20,d0        ;Großbuchstaben
  1121.         bra    1$
  1122. 2$        cmp.b    #'a',d0
  1123.         blo    1$
  1124.         cmp.b    #'z',d0
  1125.         bhi    1$
  1126.         and.b    #$df,d0        ;Kleinbuchstaben
  1127. 1$        rts
  1128.  
  1129.  
  1130. *
  1131. * Byte mit ATN über IEC-Kabel senden
  1132. * d0.b: Gerätenummer
  1133. * d1.b: Funktion
  1134. *
  1135.  
  1136. IECByteOutATN    tst.b    IECIsOpen
  1137.         bne    1$
  1138.         move.b    #ST_NOTPRESENT,d0
  1139.         rts
  1140.  
  1141. 1$        movem.l    d2/d7/a6,-(sp)
  1142.         move.b    d0,d2
  1143.         or.b    d1,d2        ;d2: Auszugebendes Byte
  1144.  
  1145.         move.l    _SysBase,a6
  1146.         JSRLIB    Disable
  1147.  
  1148.         DATA_HI
  1149.         ATN_LO
  1150.         bra    IECByteOutSec2    ;ATN response abwarten und Byte ausgeben
  1151.  
  1152.  
  1153. *
  1154. * Sekundäradresse über IEC-Kabel senden
  1155. * d0.b: Sekundäradresse
  1156. *
  1157.  
  1158. IECByteOutSec    tst.b    IECIsOpen
  1159.         bne    1$
  1160.         move.b    #ST_NOTPRESENT,d0
  1161.         rts
  1162.  
  1163. 1$        movem.l    d2/d7/a6,-(sp)
  1164.         move.b    d0,d2        ;d2: Auszugebendes Byte
  1165.  
  1166.         move.l    _SysBase,a6
  1167.         JSRLIB    Disable
  1168.  
  1169. IECByteOutSec2    CLOCK_LO
  1170.         DATA_HI
  1171.         bsr    Wait1ms        ;Max ATN response abwarten
  1172.         moveq    #0,d1        ;Kein EOI
  1173.         bra    IECByteOut2    ;Byte ausgeben
  1174.  
  1175.  
  1176. *
  1177. * Byte über IEC-Kabel senden
  1178. * d0.b: Byte
  1179. * d1.b: EOI-Flag
  1180. *
  1181.  
  1182. IECByteOut    tst.b    IECIsOpen
  1183.         bne    1$
  1184.         move.b    #ST_NOTPRESENT,d0
  1185.         rts
  1186.  
  1187. 1$        movem.l    d2/d7/a6,-(sp)
  1188.         move.b    d0,d2        ;d2: Auszugebendes Byte
  1189.  
  1190.         move.l    _SysBase,a6
  1191.         JSRLIB    Disable
  1192.  
  1193. ; Übertragung einleiten
  1194. IECByteOut2    move.b    d1,d7        ;d7: EOI-Flag
  1195.         DATA_HI
  1196.         GET_DATA_CLOCK        ;Data bleibt high -> Device not present
  1197.         bcs    IBODevNotPr
  1198.         CLOCK_HI        ;Talker ready
  1199.  
  1200.         WAIT_DATA_HI        ;Warten auf Listener ready for data
  1201.  
  1202.         tst.b    d7        ;EOI?
  1203.         bpl    1$
  1204.  
  1205.         WAIT_DATA_LO        ;Ja, EOI-Handshake abwarten
  1206.         WAIT_DATA_HI
  1207.  
  1208. 1$        CLOCK_LO        ;Talker sending
  1209.  
  1210.         bsr    Wait40us    ;Wichtige Verzögerung, aber wozu?
  1211.  
  1212. ; 8 Bits übertragen
  1213.         moveq    #7,d7        ;d7: Bitzähler
  1214. IBOBitLoop    GET_DATA_CLOCK        ;Data low -> Time out
  1215.         bcc    IBOTimeOut
  1216.  
  1217.         lsr.b    #1,d2        ;Nächstes Bit holen
  1218.         bcc    1$        ;und ausgeben
  1219.         DATA_HI
  1220.         bra    2$
  1221. 1$        DATA_LO
  1222. 2$
  1223.         bsr    Wait40us    ;Bit set-up talker delay
  1224.  
  1225.         CLOCK_HI        ;Data valid
  1226.  
  1227.         bsr    Wait20us    ;Data valid delay
  1228.  
  1229.         DATA_HI
  1230.         CLOCK_LO
  1231.  
  1232.         dbra    d7,IBOBitLoop    ;Nächstes Bit
  1233.  
  1234. ; 1ms auf Bestätigung warten
  1235.         bsr    Start1ms    ;Timer starten
  1236.  
  1237. IBODACLoop    bsr    TimerDoneQ    ;Timer abgelaufen?
  1238.         bne    IBOTimeOut    ;Ja, dann Time out
  1239.         GET_DATA_CLOCK        ;Auf Listener data accepted warten
  1240.         bcs    IBODACLoop
  1241.  
  1242. ; Alles OK
  1243.         moveq    #ST_OK,d0
  1244.         bra    IBODone
  1245.  
  1246. ; Fehlerbehandlung
  1247. IBODevNotPr    LINE_RELEASE
  1248.         move.b    #ST_NOTPRESENT,d0
  1249.         bra    IBODone
  1250.  
  1251. IBOTimeOut    LINE_RELEASE
  1252.         move.b    #ST_TIMEOUT,d0
  1253.  
  1254. IBODone        JSRLIB    Enable
  1255.  
  1256.         movem.l    (sp)+,a6/d2/d7
  1257.         rts
  1258.  
  1259.  
  1260. *
  1261. * Byte über IEC-Kabel empfangen
  1262. * Rückgabe: d1.b: Empfangenes Byte
  1263. *
  1264.  
  1265. IECByteIn    tst.b    IECIsOpen
  1266.         bne    1$
  1267.         move.b    #ST_NOTPRESENT,d0
  1268.         rts
  1269.  
  1270. 1$        movem.l    d2/d3/d7/a6,-(sp)
  1271.         moveq    #ST_OK,d3    ;d3: Status
  1272.         move.l    _SysBase,a6
  1273.         JSRLIB    Disable
  1274.  
  1275.         CLOCK_HI
  1276.         WAIT_CLOCK_HI
  1277.  
  1278. ; Auf Beginn der Übertragung warten
  1279.         bsr    Start250us    ;Timer starten
  1280.         DATA_HI            ;Listener ready for data
  1281.  
  1282. IBIWaitTalker    bsr    TimerDoneQ    ;Timer abgelaufen?
  1283.         bne    IBIEOI        ;Ja, EOI empfangen
  1284.         GET_DATA_CLOCK        ;Warten auf talker sending
  1285.         bmi    IBIWaitTalker
  1286.         bra    IBIReceive
  1287.  
  1288. ; EOI empfangen, Handshake senden und erneut auf Beginn warten
  1289. IBIEOI        move.b    #ST_EOF,d3
  1290.         DATA_LO            ;EOI handshake
  1291.         CLOCK_HI
  1292.         bsr    Wait60us    ;EOI response hold time
  1293.  
  1294.         bsr    Start250us    ;Timer starten
  1295.         DATA_HI            ;Listener ready for data
  1296.  
  1297. IBIWaitTalker2    bsr    TimerDoneQ    ;Timer abgelaufen?
  1298.         bne    IBITimeOut    ;Ja, dann Time out
  1299.         GET_DATA_CLOCK        ;Warten auf talker sending
  1300.         bmi    IBIWaitTalker2
  1301.  
  1302. ; 8 Bits empfangen
  1303. IBIReceive    moveq    #7,d7        ;d7: Bitzähler
  1304.         moveq    #0,d2        ;d2: Empfangenes Byte
  1305.  
  1306. IBIBitLoop    WAIT_CLOCK_HI        ;Auf Data valid warten
  1307.         roxr.b    #1,d2        ;Datenbit holen
  1308.         WAIT_CLOCK_LO
  1309.         dbra    d7,IBIBitLoop
  1310.  
  1311. ; Empfang bestätigen
  1312.         DATA_LO            ;Listener data accepted
  1313.         btst    #6,d3        ;EOI empfangen?
  1314.         beq    IBIDone
  1315.         LINE_RELEASE        ;Ja, Leitung freigeben
  1316.         bra    IBIDone
  1317.  
  1318. ; Fehlerbehandlung
  1319. IBITimeOut    or.b    #ST_READ_TIMEOUT,d3
  1320.         LINE_RELEASE
  1321.  
  1322. IBIDone        move.b    d3,d0        ;Status holen
  1323.         move.b    d2,d1        ;Byte holen
  1324.         JSRLIB    Enable
  1325.         movem.l    (sp)+,d2/d3/d7/a6
  1326.         rts
  1327.  
  1328.  
  1329. *
  1330. * 20µs/40µs/60µs/1ms warten
  1331. *
  1332.  
  1333. ; Timer auf 20µs setzen
  1334. Wait20us    move.l    CiaControlReg,a0
  1335.         and.b    #$80,(a0)
  1336.         move.l    CiaTimerReg,a0
  1337.         move.b    #14,(a0)
  1338.         move.b    #0,$100(a0)
  1339.         bra    StartTimer
  1340.  
  1341. ; Timer auf 40µs setzen
  1342. Wait40us    move.l    CiaControlReg,a0
  1343.         and.b    #$80,(a0)
  1344.         move.l    CiaTimerReg,a0
  1345.         move.b    #29,(a0)
  1346.         move.b    #0,$100(a0)
  1347.         bra    StartTimer
  1348.  
  1349. ; Timer auf 60µs setzen
  1350. Wait60us    move.l    CiaControlReg,a0
  1351.         and.b    #$80,(a0)
  1352.         move.l    CiaTimerReg,a0
  1353.         move.b    #43,(a0)
  1354.         move.b    #0,$100(a0)
  1355.         bra    StartTimer
  1356.  
  1357. ; Timer auf 1ms setzen
  1358. Wait1ms        move.l    CiaControlReg,a0
  1359.         and.b    #$80,(a0)
  1360.         move.l    CiaTimerReg,a0
  1361.         move.b    #$cc,(a0)
  1362.         move.b    #2,$100(a0)
  1363.         move.l    CiaControlReg,a0
  1364.  
  1365. ; Timer anwerfen (One-Shot) und auf Ablauf warten
  1366. StartTimer    move.l    a6,-(sp)
  1367.         move.l    _CiaBase,a6
  1368.  
  1369.         move.b    WhichTimerMask,d0
  1370.         JSRLIB    SetICR
  1371.  
  1372.         move.l    CiaControlReg,a0
  1373.         move.b    #CIACRAF_LOAD|CIACRAF_RUNMODE|CIACRAF_START,(a0)
  1374.  
  1375. 1$        moveq    #0,d0
  1376.         JSRLIB    SetICR
  1377.         and.b    WhichTimerMask,d0
  1378.         beq    1$
  1379.  
  1380.         move.l    (sp)+,a6
  1381.         rts
  1382.  
  1383.  
  1384. *
  1385. * Timer starten, 1ms/250µs
  1386. *
  1387.  
  1388. Start1ms    move.l    a6,-(sp)
  1389.         move.l    _CiaBase,a6
  1390.         move.l    CiaControlReg,a0
  1391.         and.b    #$80,(a0)
  1392.  
  1393.         move.l    CiaTimerReg,a0
  1394.         move.b    #$cc,(a0)
  1395.         move.b    #2,$100(a0)
  1396.  
  1397.         move.b    WhichTimerMask,d0
  1398.         JSRLIB    SetICR
  1399.  
  1400.         move.l    CiaControlReg,a0
  1401.         or.b    #CIACRAF_LOAD|CIACRAF_RUNMODE|CIACRAF_START,(a0)
  1402.         move.l    (sp)+,a6
  1403.         rts
  1404.  
  1405. Start250us    move.l    a6,-(sp)
  1406.         move.l    _CiaBase,a6
  1407.         move.l    CiaControlReg,a0
  1408.         and.b    #$80,(a0)
  1409.  
  1410.         move.l    CiaTimerReg,a0
  1411.         move.b    #$b3,(a0)
  1412.         move.b    #0,$100(a0)
  1413.  
  1414.         move.b    WhichTimerMask,d0
  1415.         JSRLIB    SetICR
  1416.  
  1417.         move.l    CiaControlReg,a0
  1418.         or.b    #CIACRAF_LOAD|CIACRAF_RUNMODE|CIACRAF_START,(a0)
  1419.         move.l    (sp)+,a6
  1420.         rts
  1421.  
  1422.  
  1423. *
  1424. * Timer abgelaufen?
  1425. * bne: Ja
  1426. *
  1427.  
  1428. TimerDoneQ    move.l    a6,-(sp)
  1429.         move.l    _CiaBase,a6
  1430.         moveq    #0,d0
  1431.         JSRLIB    SetICR
  1432.         and.b    WhichTimerMask,d0
  1433.         move.l    (sp)+,a6
  1434.         tst.b    d0
  1435.         rts
  1436.  
  1437.  
  1438. *
  1439. * Dummy-Timer-Interrupt-Routine
  1440. *
  1441.  
  1442. IntTimer    moveq    #0,d0
  1443.         rts
  1444.  
  1445.  
  1446. **
  1447. ** Konstanten
  1448. **
  1449.  
  1450. ; Tabelle für Fehlermeldungen (Index: ErrorCode)
  1451.         CNOP    0,4
  1452. ErrorTab    dc.l    OKText
  1453.         dc.l    StartupText
  1454.         dc.l    FileNotFText
  1455.  
  1456. ; Fehlertexte
  1457. OKText        dc.b    "00, OK,00,00",13
  1458. StartupText    dc.b    "73,CBM DOS V2.6 1541,00,00",13
  1459. FileNotFText    dc.b    "62, FILE NOT FOUND,00,00",13
  1460.  
  1461. ; Tabelle mit Zeigern auf die Laufwerks-Datenstrukturen
  1462.         CNOP    0,4
  1463. DrvTab        dc.l    Drv8Data
  1464.         dc.l    Drv9Data
  1465.         dc.l    Drv10Data
  1466.         dc.l    Drv11Data
  1467.  
  1468. ; Name der temporären Datei für das Directory
  1469. TempFileName    dc.b    "T:Frodo$File",0
  1470.  
  1471. ; Name für AllocMiscResource
  1472. ParPortName    dc.b    "Frodo Parallel Port",0
  1473.  
  1474. ; Name des Timer-Interrupts
  1475. TimerIntName    dc.b    "Frodo Timer Int",0
  1476.         CNOP    0,4
  1477.  
  1478.  
  1479. **
  1480. ** Initialisierte Daten
  1481. **
  1482.  
  1483.         SECTION    "DATA",DATA
  1484.  
  1485. TimerInterrupt    dc.l    0,0
  1486.         dc.b    NT_INTERRUPT,0
  1487.         dc.l    TimerIntName
  1488.         dc.l    0
  1489.         dc.l    IntTimer
  1490.  
  1491.  
  1492. **
  1493. ** Nicht initialisierte Daten
  1494. **
  1495.  
  1496.         SECTION    "BSS",BSS
  1497.  
  1498. ; Global
  1499. ListenerActive    ds.b    1    ;Flag: Listener angewählt, ListenerData ist gültig
  1500. ListenerIsIEC    ds.b    1    ;Flag: Aktiver Listener hängt am IEC-Kabel (impliziert ListenerActive)
  1501. TalkerActive    ds.b    1    ;Flag: Talker angewählt, TalkerData ist gültig
  1502. TalkerIsIEC    ds.b    1    ;Flag: Aktiver Talker hängt am IEC-Kabel (impliziert TalkerActive)
  1503.  
  1504. Listening    ds.b    1    ;Flag: Letzter ATN-Befehl war Listen (für SecListen/SecTalk-Unterscheidung)
  1505. SecAddr        ds.b    1    ;Aktuelle Sekundäradresse ($0x)
  1506. ReceivedCmd    ds.b    1    ;Empfangener Befehlscode ($x0)
  1507.  
  1508. IECIsOpen    ds.b    1    ;Flag: Timer und Port belegt, IEC-Kabel kann benutzt werden
  1509.  
  1510. WhichTimer    ds.b    1    ;Welcher Timer wurde belegt? (0: Timer A, 1: Timer B)
  1511. WhichTimerMask    ds.b    1    ;Dto. als Bit-Maske für ICR
  1512.  
  1513.         CNOP    0,4
  1514. CiaTimerReg    ds.l    1    ;Zeiger auf Cia-Timer-Register
  1515. CiaControlReg    ds.l    1
  1516.  
  1517. ListenerData    ds.l    1    ;Zeiger auf Struktur des aktiven Listeners
  1518. TalkerData    ds.l    1    ;Zeiger auf Struktur des aktiven Talkers
  1519.  
  1520. ; Datenstruktur pro Laufwerk
  1521. Drv8Data    ds.b    drv_SIZEOF
  1522. Drv9Data    ds.b    drv_SIZEOF
  1523. Drv10Data    ds.b    drv_SIZEOF
  1524. Drv11Data    ds.b    drv_SIZEOF
  1525.  
  1526. ; Puffer für die Verzeichnisse der 4 Laufwerke
  1527. Dir8        ds.b    256
  1528. Dir9        ds.b    256
  1529. Dir10        ds.b    256
  1530. Dir11        ds.b    256
  1531.  
  1532. ; Puffer für Dateinamen
  1533. NameBuf        ds.b    64
  1534.  
  1535. ; Einstellungen
  1536. Drv8IsIEC    ds.w    1
  1537. Drv9IsIEC    ds.w    1
  1538. Drv10IsIEC    ds.w    1
  1539. Drv11IsIEC    ds.w    1
  1540. OtherIEC    ds.w    1
  1541.  
  1542.         CNOP    0,4
  1543. TheFIB        ds.b    fib_SIZEOF    ;FileInfoBlock
  1544.  
  1545.         END
  1546.